View Javadoc

1   /*
2    * FQAN.java
3    *
4    * Created on September 10, 2004, 12:14 PM
5    */
6   
7   package gov.bnl.gums;
8   
9   import java.util.StringTokenizer;
10  import java.util.regex.Matcher;
11  import java.util.regex.Pattern;
12  
13  /*** Represent a VOMS extended proxy credential as defined in
14   * http://edg-wp2.web.cern.ch/edg-wp2/security/voms/edg-voms-credential.pdf.
15   * <p>
16   * A Fully Qualified Attribute Name consists of a VO, a group, a role and
17   * a capability. Only the VO is mandatory. The syntax is
18   * /VO[/group[/subgroup(s)]][/Role=role][/Capability=cap].
19   * <p>
20   * The class will always check that every modification matches the regex
21   * /[\w-\.]+(/[\w-\.]+)*(/Role=[\w-\.]+)?(/Capability=[\w-\.]+)?
22   * which fully defines all the characters allowed. This differs slightly from
23   * the one contained in the specification, as it cointained some small errors.
24   * It matches the description of the syntax of the document.
25   *
26   * @author  Gabriele Carcassi
27   */
28  public class FQAN {
29      
30      private String fqan;
31      private String vo;
32      private String group;
33      private String role;
34      private String capability;
35      
36      // Compiling this huge pattern requires time...
37      // Let's do it once.
38      private static Pattern fqanPattern = Pattern.compile("/[//w-//.]+(/[//w-//.]+)*(/Role=[//w-//.]+)?(/Capability=[//w-//.]+)?");
39      
40      /***
41       * Creates a FQAN based on String representation. If the parsing fails, it will
42       * throw an exception.
43       * @param fqan A VOMS FQAN (i.e. "/atlas/production/Role=Leader")
44       */
45      public FQAN(String fqan) {
46          setFqan(fqan);
47          parseFqan(fqan);
48          generateFqan();
49      }
50      
51      /*** Creates a FQAN based on the different pieces of information.
52       * 
53       * @param vo The VO name, which cannot be null (i.e. "atlas")
54       * @param group A group path, including subgroups (i.e. "/production")
55       * @param role The role (i.e. "Leader")
56       * @param capability A capability (i.e. "capability"). Note capabilities are
57       * being deprecated in VOMS.
58       */
59      public FQAN(String vo, String group, String role, String capability) {
60          if (vo == null)
61              throw new IllegalArgumentException("The vo for a FQAN can't be null");
62          setVo(vo);
63          setGroup(group);
64          setRole(role);
65          setCapability(capability);
66          generateFqan();
67      }
68      
69      /*** A full String representation of the FQAN.
70       * 
71       * @return The Fully Qualified Attribute name String representation (i.e. "/atlas/production/Role=Leader")
72       */
73      public String getFqan() {
74          return this.fqan;
75      }
76  
77      private void setFqan(String fqan) {
78          this.fqan = fqan;
79      }
80  
81      /*** Returns the VO corresponding to the FQAN.
82       * 
83       * @return The VO name (i.e. "atlas")
84       */
85      public String getVo() {
86          return this.vo;
87      }
88      
89      private void setVo(String vo) {
90          if ((vo != null) && (!vo.matches("[//w-//.]+"))) {
91              throw new IllegalArgumentException("The vo '" + vo + "' is malformed");
92          }
93          this.vo = vo;
94      }
95      
96      /*** The path which includes the groups and subgroups within the FQAN.
97       * 
98       * @return The group path (i.e. "/production")
99       */
100     public String getGroup() {
101         return this.group;
102     }
103     
104     private void setGroup(String group) {
105         if ((group != null) && (!group.matches("(/[//w-//.]+)+"))) {
106             throw new IllegalArgumentException("The group '" + group + "' is malformed");
107         }
108         this.group = group;
109     }
110     
111     /*** The role used within the FQAN.
112      * 
113      * @return The role or null if no role was specified
114      */
115     public String getRole() {
116         return this.role;
117     }
118     
119     private void setRole(String role) {
120         if ((role != null) && (!role.matches("[//w-//.]+"))) {
121             throw new IllegalArgumentException("The role '" + role + "' is malformed");
122         }
123         this.role = role;
124         if ("NULL".equalsIgnoreCase(role)) {
125             this.role = null;
126         }
127     }
128     
129     /***
130      *  The capability used within the FQAN.
131      * @return The capability or null if none was specified.
132      */
133     public String getCapability() {
134         return this.capability;
135     }
136     
137     private void setCapability(String capability) {
138         if ((capability != null) && (!capability.matches("[//w-//.]+"))) {
139             throw new IllegalArgumentException("The capability '" + capability + "' is malformed");
140         }
141         this.capability = capability;
142         if ("NULL".equalsIgnoreCase(capability)) {
143             this.capability = null;
144         }
145     }
146     
147     private void parseFqan(String fqan) {
148         // Matches to the specification.
149         Matcher m = fqanPattern.matcher(fqan);
150         if (!m.matches())
151             throw new IllegalArgumentException("FQAN '" + fqan + "' is malformed (syntax: /VO[/group[/subgroup(s)]][/Role=role][/Capability=cap])");
152         
153         StringTokenizer stk = new StringTokenizer(fqan, "/");
154         vo = stk.nextToken();
155         if (!stk.hasMoreTokens()) {
156             group = null;
157             role = null;
158             capability = null;
159             return;
160         }
161         String tempGroup = "";
162         String token = stk.nextToken();
163         while ((!token.startsWith("Role=") && !token.startsWith("Capability="))) {
164             tempGroup = tempGroup + "/" + token;
165             group = tempGroup;
166             if (!stk.hasMoreTokens()) {
167                 role = null;
168                 capability = null;
169                 return;
170             }
171             token =  stk.nextToken();
172         }
173         if (token.startsWith("Role=")) {
174             setRole(token.substring(5));
175             if (!stk.hasMoreTokens()) {
176                 capability = null;
177                 return;
178             }
179             token = stk.nextToken();
180         }
181         if (token.startsWith("Capability=")) {
182             setCapability(token.substring(11));
183         }
184     }
185     
186     private void generateFqan() {
187         if (vo == null) {
188             fqan = null;
189             return;
190         }
191         StringBuffer bf = new StringBuffer();
192         bf.append('/');
193         bf.append(vo);
194         if (group != null)
195             bf.append(group);
196         if (role != null) {
197             bf.append("/Role=");
198             bf.append(role);
199         }
200         if (capability != null) {
201             bf.append("/Capability=");
202             bf.append(capability);
203         }
204         fqan = bf.toString();
205     }
206     
207     /*** Returns the full string representation of the FQAN.
208      * 
209      * @return The full FQAN (i.e. "/atlas/production/Role=Leader")
210      */
211     public String toString() {
212         return fqan;
213     }
214     
215     /*** A hashcode generated from the string representation.
216      * 
217      * @return A hashcode.
218      */
219     public int hashCode() {
220         if (fqan == null) return 0;
221         return fqan.hashCode();
222     }
223     
224     /*** FQANs are equals to each other if their vo, group, role and capability
225      * are the same.
226      * 
227      * @param obj Another object.
228      * @return True if the object was a FQAN with equal information. False otherwise.
229      */
230     public boolean equals(Object obj) {
231         if (obj == null) return false;
232         FQAN fqan2 = (FQAN) obj;
233         return (fqan2.fqan == null) ? fqan == null : fqan2.fqan.equals(fqan);
234     }
235     
236 }